#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <linux/if.h>
//#include <linux/in.h>
#include <string.h>
#include <linux/sockios.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
//#include <bits/param.h>

#define IP_SIZE 128
#define PROCBUFSIZ                  1024
#define _PATH_PROC_NET_DEV        "/proc/net/dev"

char ethname[]="eth0";

#ifndef NOFILE
#define NOFILE 256
#endif


static char * interface_name_cut (char *buf, char **name)
{
  char *stat;
  /* Skip white space.  Line will include header spaces. */
  while (*buf == ' ')
    buf++;
  *name = buf;
  /* Cut interface name. */
  stat = strrchr (buf, ':');
  *stat++ = '\0';
  return stat;
}
/*
return value:1 exist 0:no
*/ 
int check_interface_fromproc(char *interface)
{
  FILE *fp;
  char buf[PROCBUFSIZ];
  struct interface *ifp;
  char *name;
 
  /* Open /proc/net/dev. */
  fp = fopen (_PATH_PROC_NET_DEV, "r");
  if (fp == NULL)
    {   
        printf("open proc file error\n");
      return -1; 
    }   
 
  /* Drop header lines. */
  fgets (buf, PROCBUFSIZ, fp);
  fgets (buf, PROCBUFSIZ, fp);
 
  /* Only allocate interface structure.  Other jobs will be done in
     if_ioctl.c. */
  while (fgets (buf, PROCBUFSIZ, fp) != NULL)
    {   
      interface_name_cut (buf, &name);
      if(strcmp(interface,name)==0)
          return 1;
    }   
  fclose(fp);
  return 0;
}
/**
 * 获取本地IP
 * @param eth
 * @param ip
 * @return
 */
int getLocalIp(const char *eth, char *ip) {
    struct ifreq ifr;
    struct sockaddr_in sin;
    int fd;
    bzero(&ifr, sizeof(ifr));
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        return -1;
    }
    strcpy(ifr.ifr_name, eth);
    if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
        close(fd);
        return -1;
    }
    memcpy(&sin, &ifr.ifr_addr, sizeof(sin));
    snprintf(ip, IP_SIZE, "%s", inet_ntoa(sin.sin_addr));
    close(fd);
    return 0;
}
int setIpAddrManual(const char *eth, char *ipstr) {
    int fd;
    struct sockaddr_in sin;
    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return -1;
    }
    strcpy(ifr.ifr_name, eth);

	sin.sin_addr.s_addr = inet_addr(ipstr);
	
	sin.sin_family = AF_INET;
    memcpy(&ifr.ifr_addr, &sin, sizeof(sin));
	
    if (ioctl(fd, SIOCSIFADDR, &ifr) < 0)
    {
    	perror("");
        close(fd);
        return -1;
    }
    close(fd);
    return 0;
} 

int getLocalMac(const char *eth, char *mac) {


    int fd;
    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return -1;
    }
    strcpy(ifr.ifr_name, eth);
    if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0)
    {
        close(fd);
        return -1;
    }
   snprintf(mac,18, "%02x:%02x:%02x:%02x:%02x:%02x",
         (unsigned char) ifr.ifr_hwaddr.sa_data[0],
         (unsigned char) ifr.ifr_hwaddr.sa_data[1],
         (unsigned char) ifr.ifr_hwaddr.sa_data[2],
         (unsigned char) ifr.ifr_hwaddr.sa_data[3],
         (unsigned char) ifr.ifr_hwaddr.sa_data[4],
         (unsigned char) ifr.ifr_hwaddr.sa_data[5]);
    close(fd);
    return 0;

} 
/*
support format [00:11:22:33:44:55]
*/
#define MAC_ARRAY(mac_array)  (unsigned int *)&mac_array[0],(unsigned int *)&mac_array[1],(unsigned int *)&mac_array[2],(unsigned int *)&mac_array[3],(unsigned int *)&mac_array[4],(unsigned int *)&mac_array[5] 
int setLocalMac(const char *eth, char *mac) {
    int fd;
    struct ifreq ifr;
	unsigned char mac_array[6] = {0};
	
    bzero(&ifr, sizeof(ifr));
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return -1;
    }
    strcpy(ifr.ifr_name, eth);
	ifr.ifr_hwaddr.sa_family = AF_LOCAL;
	
	sscanf(mac,"%02x:%02x:%02x:%02x:%02x:%02x",
		MAC_ARRAY(mac_array));

	memcpy(ifr.ifr_hwaddr.sa_data,mac_array,6);

    if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0)
    {
    	perror("SIOCSIFHWADDR:");
        close(fd);
        return -1;
    }

    close(fd);
    return 0;
} 

int getMtu(const char *eth, char *mtu) {
    int fd;
    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return -1;
    }
    strcpy(ifr.ifr_name, eth);
    if (ioctl(fd, SIOCGIFMTU, &ifr) < 0)
    {
        close(fd);
        return -1;
    }	
   	snprintf(mtu,64, "%d", (unsigned char) ifr.ifr_mtu);
    close(fd);
    return 0;
} 
int getDestAddr(const char *eth, char *ip) {
    int fd;
    struct sockaddr_in sin;
    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return -1;
    }
    strcpy(ifr.ifr_name, eth);
    if (ioctl(fd, SIOCGIFDSTADDR, &ifr) < 0)
    {
    	perror("");
        close(fd);
        return -1;
    }
    memcpy(&sin, &ifr.ifr_dstaddr, sizeof(sin));
    snprintf(ip, IP_SIZE, "%s", inet_ntoa(sin.sin_addr));

    close(fd);
    return 0;

} 

int getBroadAddr(const char *eth, char *ip) {
    int fd;
    struct sockaddr_in sin;
    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return -1;
    }
    strcpy(ifr.ifr_name, eth);
    if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
    {
    	perror("");
        close(fd);
        return -1;
    }
    memcpy(&sin, &ifr.ifr_broadaddr, sizeof(sin));
    snprintf(ip, IP_SIZE, "%s", inet_ntoa(sin.sin_addr));

    close(fd);
    return 0;
} 
int getNetMask(const char *eth, char *mask) {
    int fd;
    struct sockaddr_in sin;
    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return -1;
    }
    strcpy(ifr.ifr_name, eth);
    if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
    {
    	perror("");
        close(fd);
        return -1;
    }
    memcpy(&sin, &ifr.ifr_netmask, sizeof(sin));
    snprintf(mask, IP_SIZE, "%s", inet_ntoa(sin.sin_addr));

    close(fd);
    return 0;
}
int getFlags(const char *eth, char *fg) {
    int fd;
    struct sockaddr_in sin;
    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return -1;
    }
    strcpy(ifr.ifr_name, eth);
    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0)
    {
    	perror("");
        close(fd);
        return -1;
    }
	snprintf(fg, IP_SIZE, "%x", ifr.ifr_flags);

    close(fd);
    return 0;
} 
int getTxQueueLen(const char *eth, char *buf) {
    int fd;
    struct sockaddr_in sin;
    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));
    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return -1;
    }
    strcpy(ifr.ifr_name, eth);
    if (ioctl(fd, SIOCGIFTXQLEN, &ifr) < 0)
    {
    	perror("");
        close(fd);
        return -1;
    }
	snprintf(buf, IP_SIZE, "%d", ifr.ifr_qlen);

    close(fd);
    return 0;
} 

int main(int argc, char **argv)
{
	int fg=0;
	char mac[32]={};
	char ip[IP_SIZE]={0};
	char buf[64];

	fg=check_interface_fromproc(ethname);
	if(fg == 1)
	{
		getBroadAddr(ethname,ip);
		printf("broad ip:\t%s\n",ip);

		getNetMask(ethname,ip);
		printf("mask:\t%s\n",ip);
		
		setIpAddrManual(ethname, "1.1.1.1");
		getLocalIp(ethname,ip);
		printf("ip:\t%s\n",ip);
		
		setLocalMac(ethname,"00:11:22:33:44:55");
		getLocalMac(ethname,mac);
		printf("mac:\t%s\n",mac);

		getMtu(ethname,buf);
		printf("mtu:\t%s\n",buf);	
	}
	return 1;
}

